
#include "eiot.h"
#include "api.h"
#include "../../../include/common.h"

int EIOT_Init(cfg_pu_t* pu);
int EIOT_Run(cfg_pu_t* pu);
int EIOT_Msg(cfg_pu_t* pu, msg_t *msg);

dlmodule_t EIOT = {
    EIOT_Init,
    EIOT_Run,
    EIOT_Msg
};

static int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    printf("Message arrived\n");
    printf("  Topic: %s\n", topicName);
    printf("Payload: %.*s\n", message->payloadlen, (char *)message->payload);

    mqtt_handle_t *handle = (mqtt_handle_t *)context;
    cfg_pu_t *pu = (cfg_pu_t *)handle->param;

    pu->pkg_recv++;

    if (strstr(topicName, "sys/server") != NULL)
    {
        cJSON *root = cJSON_Parse((char *)message->payload);
        if (root == NULL)
        {
            const char *error_ptr = cJSON_GetErrorPtr();
            if (error_ptr != NULL)
            {
                LOG_E("eiot", "Error before: %s\n", error_ptr);
            }
            goto msg_proc_done;
        }

        cJSON *sn = cJSON_GetObjectItem(root, "sn");
        cJSON *method = cJSON_GetObjectItem(root, "method");
        cJSON *msgid = cJSON_GetObjectItem(root, "msgid");
        cJSON *timestamp = cJSON_GetObjectItem(root, "timestamp");

        if (sn == NULL || method == NULL || msgid == NULL || timestamp == NULL)
        {
            cJSON_Delete(root);
            goto msg_proc_done;
        }

        if (strcmp(method->valuestring, "restart") == 0)
        {
            api_restart_rsp(handle, msgid->valuestring, timestamp->valueint);
            cJSON_Delete(root);
            system("reboot");
        }
        else if (strcmp(method->valuestring, "info") == 0)
        {
            cJSON *cJSON_Payload = cJSON_GetObjectItem(root, "payload");
            cJSON *cmd = cJSON_GetObjectItem(cJSON_Payload, "cmd");
            cJSON *type = cJSON_GetObjectItem(cJSON_Payload, "type");

            if (strcmp(cmd->valuestring, "READ") == 0 && strcmp(type->valuestring, "BASIC") == 0)
            {
                api_read_basic_rsp(handle, msgid->valuestring, timestamp->valueint);
                cJSON_Delete(root);
            }
            else if (strcmp(cmd->valuestring, "READ") == 0 && strcmp(type->valuestring, "STATIC") == 0)
            {
                api_read_static_rsp(handle, msgid->valuestring, timestamp->valueint);
                cJSON_Delete(root);
            }
        }
    }


msg_proc_done:
    MQTTClient_freeMessage(&message);
    MQTTClient_free(topicName);
    return 1;
}

int EIOT_Init(cfg_pu_t *pu)
{
    UTIL_LOG_I(pu, "init");

    cJSON *root = pu->hanlder.cjson;
    if(NULL == root)
    {
        UTIL_LOG_E(pu,"trans protocol setting cJSON is NULL");
        return -1;
    }

    // 解析协议参数
    cJSON *IP = cJSON_GetObjectItem(root, "IP");
    if (IP == NULL)
    {
        return -1;
    }
    cJSON *Port = cJSON_GetObjectItem(root, "Port");
    if (Port == NULL)
    {
        return -1;
    }

    mqtt_handle_t *handle = (mqtt_handle_t *)malloc(sizeof(mqtt_handle_t));

    handle->server_ip = awt_string_duplicate(IP->valuestring);
    handle->server_port = awt_string_duplicate(Port->valuestring);
    handle->reconnect = 60;
    handle->param = pu;
    pu->hanlder.param = handle;

    if(root) cJSON_Delete(root);

    char client_id[100] = "";
    sprintf(client_id, "%s", "TEST0123456789");
    char address[100] = "";

    sprintf(address, "%s:%s", handle->server_ip, handle->server_port);
    MQTTClient client;
    if (MQTTClient_create(&client, address, client_id, MQTTCLIENT_PERSISTENCE_NONE, NULL) != MQTTCLIENT_SUCCESS)
    {
        LOG_E("EIOT", "%s Failed to create client object",pu->name);
        free(handle);
        return -1;
    }

    handle->client = client;
    if (MQTTClient_setCallbacks(client, handle, NULL, msgarrvd, NULL) != MQTTCLIENT_SUCCESS)
    {
        LOG_E("EIOT", "%s Failed to set callback",pu->name);
        free(handle);
        return 0;
    }

    return 0;
}

int EIOT_Run(cfg_pu_t *pu)
{
    LOG_I("EIOT","%s---running----",pu->name);

    api_t *api = (api_t *)pu->hanlder.api;
    mqtt_handle_t *handle = (mqtt_handle_t *)pu->hanlder.param;

    while (1)
    {
        MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
        conn_opts.keepAliveInterval = 20;
        conn_opts.cleansession = 1;

        conn_opts.username = NULL;
        conn_opts.password = NULL;

        if (MQTTClient_connect(handle->client, &conn_opts) != MQTTCLIENT_SUCCESS)
        {
            LOG_E("EIOT", "%s Failed to connect the mqtt broker: %s:%s",pu->name,handle->server_ip,handle->server_port);
            msleep(handle->reconnect * 1000);
            continue;
        }
        LOG_I("EIOT", "%s connect the mqtt broker:%s:%s successfully!",pu->name,handle->server_ip,handle->server_port);

        char sub_topic1[200] = "";
        sprintf(sub_topic1, "indicate/server/ODQwODQ3MTgzNzA0Mjg5Mjgw/%s","TEST0123456789");
        if (MQTTClient_subscribe(handle->client, sub_topic1, 0) != MQTTCLIENT_SUCCESS)
        {
            LOG_W("EIOT", "%s Failed to subscribe topic1: %s!",pu->name,sub_topic1);
            msleep(handle->reconnect * 1000);
            continue;
        }
        LOG_I("EIOT", "%s Succeed in subscribing the topic1:%s successfully!",pu->name,sub_topic1);

        char sub_topic2[200] = "";
        sprintf(sub_topic2, "sys/server/ODQwODQ3MTgzNzA0Mjg5Mjgw/%s","TEST0123456789");
        if (MQTTClient_subscribe(handle->client, sub_topic2, 0) != MQTTCLIENT_SUCCESS)
        {
            LOG_W("EIOT", "%s Failed to subscribe topic2: %s!",pu->name,sub_topic2);
            msleep(handle->reconnect * 1000);
            continue;
        }
        LOG_I("EIOT", "%s Succeed in subscribing the topic2:%s successfully!",pu->name,sub_topic2);

        // login sys/dev/{productKey}/{sn}
        api_login(handle);

        while (1)
        {
            if (!MQTTClient_isConnected(handle->client))
            {
                LOG_W("EIOT", "%s mqtt disconnect,reconnecting...",pu->name);
                break;
            }

            msleep(1000);
        }
    }
}

int EIOT_Msg(cfg_pu_t *pu, msg_t *msg)
{

    return 0;
}